package org.e_gold.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.e_gold.dao.CookieDAO;
import org.e_gold.dto.Cookies;
import org.e_gold.service.CookieService;
import org.e_gold.util.Constant;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public class _NavigatorService implements Constant, InitializingBean {

	private static final Logger logger = Logger.getLogger(_NavigatorService.class);
	Connection connection;
	protected static Cookies cookies;
	protected static Map<String, String> headers;

	@Autowired
	private CookieService cookieService;

	@Autowired
	private CookieDAO cookieDAO;

	@Override
	public void afterPropertiesSet() throws Exception {

		// init header + cookies
		headers = prepareBasicHeaders();
		if(CollectionUtils.isNotEmpty(cookieDAO.findAll())){
			// re-store cookie for logined session or basic session for the first time
			if (cookies == null) {
				cookies = new Cookies();
			}
			if (cookies.getCookies() == null) {
				cookies.setCookies(cookieDAO.findAll());
			}
			headers.put(COOKIE, cookies.getCookie());
		} else {
			try {
				redirectNavigator(DEFAULT_URL);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public Connection navigator(String url) {

		Connection connection = Jsoup.connect(url);
		for (Map.Entry<String, String> entry : headers.entrySet()) {
			connection.header(entry.getKey(), entry.getValue());
		}
		if (cookies != null && cookies.getCookieMap() != null && cookies.getCookieMap().size() > 0) {
			connection.cookies(cookies.getCookieMap());
			connection.header(COOKIE, cookies.getCookie());
		}
		connection.followRedirects(false);
		return connection;
	}

	public Map<String, String> prepareBasicHeaders() {

		Map<String, String> basicHeader = new HashMap<String, String>();
		basicHeader.put(ACCEPT, ACCEPT_DATA);
		basicHeader.put(ACCEPT_ENCODING, ACCEPT_ENCODING_DATA);
		basicHeader.put(ACCEPT_LANGUAGE, ACCEPT_LANGUAGE_DATA);
		basicHeader.put(CONNECTION, CONNECTION_DATA);
		basicHeader.put(HOST, HOST_DATA);
		basicHeader.put(USER_AGENT, USER_AGENT_DATA);
		basicHeader.put(CACHE_CONTROL, CACHE_CONTROL_DATA);
		basicHeader.put(PRAGMA, PRAGMA_DATA);
		return basicHeader;
	}

	public Document redirectNavigator(String url) throws Exception {

		Document doc = null;
		try {
			connection = navigator(url).timeout(30000);
			doc = connection.get();
			while (responseCode(connection) == HttpStatus.FOUND.value()) {
				String redirectLocation = connection.response().header(LOCATION);
				if (cookies == null) {
					cookies = new Cookies();
				}
				cookies.putNewCookies(connection.response().cookies());
				cookieService.saveCookies(cookies);
				connection = navigator(redirectLocation);
				doc = connection.get();
			}
		} catch (Exception e) {
			logger.error("redirectNavigator error : " + url);
			throw e;
		}

		return doc;
	}

	public Document postForm(String url, Map<String, String> formData) {

		Document doc = null;
		try {
			connection = navigator(url).timeout(30000).data(formData);
			doc = connection.post();
			while (responseCode(connection) == HttpStatus.FOUND.value()) {
				headers.remove(CONTENT_TYPE);
				cookies.putNewCookies(connection.response().cookies());
				// update current cookie
				cookieService.saveCookies(cookies);
				String redirectLocation = connection.response().header(LOCATION);
				connection = navigator(redirectLocation);
				doc = connection.get();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return doc;
	}

	public int responseCode(Connection connection) {

		return connection.response().statusCode();
	}

}
